#ifndef DELAYDEVICE_H
#define DELAYDEVICE_H

#include <QObject>
#include <QString>
#include <QMutex>
#include <QAtomicInt>
#include "DelayCamerDevice_C.h"
#include <QVariantMap>

//参数的名称

//触发模式
#define TRIGGER_MODE "TriggerMode"
//精延迟使能
#define PRECISE_DELAY_ENABLE "PreciseDelayEnable"
//精延迟使能(T0)
#define PRECISE_DELAY_ENABLE_T0 PRECISE_DELAY_ENABLE"_T0"
//精延迟使能(T1)
#define PRECISE_DELAY_ENABLE_T1 PRECISE_DELAY_ENABLE"_T1"
//精延迟使能(T2)
#define PRECISE_DELAY_ENABLE_T2 PRECISE_DELAY_ENABLE"_T2"
//FOCUS模式下，精延迟的信号的宽度
#define PRECISE_DELAY_WIDTH_F "PreciseDelayWidth_f"
//FOCUS模式下，精延迟的信号的周期
#define PRECISE_DELAY_PERIOD_F "PreciseDelayPeriod_f"
//精延迟的延时
#define PRECISE_DELAY_TIME "PreciseDelayTime"
//精延迟的延时(T0)
#define PRECISE_DELAY_TIME_T0 PRECISE_DELAY_TIME"_T0"
//精延迟的延时(T1)
#define PRECISE_DELAY_TIME_T1 PRECISE_DELAY_TIME"_T1"
//精延迟的延时(T2)
#define PRECISE_DELAY_TIME_T2 PRECISE_DELAY_TIME"_T2"
//精延迟的脉宽
#define PRECISE_DELAY_WIDTH "PreciseDelayWidth"
//精延迟的脉宽(T0)
#define PRECISE_DELAY_WIDTH_T0 PRECISE_DELAY_WIDTH"_T0"
//精延迟的脉宽(T1)
#define PRECISE_DELAY_WIDTH_T1 PRECISE_DELAY_WIDTH"_T1"
//精延迟的脉宽(T2)
#define PRECISE_DELAY_WIDTH_T2 PRECISE_DELAY_WIDTH"_T2"
//IO值
#define IO_VALUE "IOValue"
//IO值(通道1)
#define IO_VALUE_1 IO_VALUE"_1"
//IO值(通道2)
#define IO_VALUE_2 IO_VALUE"_2"
//DA值
#define DA_VALUE "DAValue"
//DA值(通道1)
#define DA_VALUE_1 DA_VALUE"_1"
//DA值(通道2)
#define DA_VALUE_2 DA_VALUE"_2"
//AD值
#define AD_VALUE "ADValue"
//AD值(通道1)
#define AD_VALUE_1 AD_VALUE"_1"
//AD值(通道2)
#define AD_VALUE_2 AD_VALUE"_2"
//上升沿延时(TO)
#define RISE_EDGE_DELAY_T0 "RiseEdgeDelay_T0"
//上升沿延时(T1)
#define RISE_EDGE_DELAY_T1 "RiseEdgeDelay_T1"
//下降沿延时(T1)
#define FALL_EDGE_DELAY_T1 "FallEdgeDelay_T1"
//上升沿延时(T2)
#define RISE_EDGE_DELAY_T2 "RiseEdgeDelay_T2"
//下降沿延时(T2)
#define FALL_EDGE_DELAY_T2 "FallEdgeDelay_T2"
//上升沿脉宽(TO)
#define RISE_EDGE_WIDTH_T0 "RiseEdgeWidth_T0"
//上升沿脉宽(T1)
#define RISE_EDGE_WIDTH_T1 "RiseEdgeWidth_T1"
//下降沿脉宽(T1)
#define FALL_EDGE_WIDTH_T1 "FallEdgeWidth_T1"
//上升沿脉宽(T2)
#define RISE_EDGE_WIDTH_T2 "RiseEdgeWidth_T2"
//下降沿脉宽(T2)
#define FALL_EDGE_WIDTH_T2 "FallEdgeWidth_T2"
//是否写入闪存
#define IS_WRITE_FLASHE  "IsWriteFlash"

/**
 * @brief DelayDevice类 - 负责与延时设备进行直接通信和控制
 * @details 提供设备连接、参数设置、状态查询等功能
 */
class DelayDevice : public QObject
{
    Q_OBJECT
public:
    explicit DelayDevice(const QString& deviceIp, QObject *parent = nullptr);
    ~DelayDevice() override;

    /**
     * @brief 打开设备连接
     * @return 连接成功返回true，失败返回false
     */
    bool open();

    /**
     * @brief 关闭设备连接
     */
    void close();

    /**
     * @brief 获取设备IP地址
     * @return 设备IP地址字符串
     */
    QString deviceIp() const { return m_deviceIp; }

    /**
     * @brief 检查设备是否已连接
     * @return 已连接返回true，否则返回false
     */
    bool isConnected() const { return m_isConnected; }

    /**
     * @brief 获取设备参数
     * @param paramName 参数名称
     * @return 参数值，失败返回无效的QVariant
     */
    QVariant getParameter(const QString& paramName) const;

    /**
     * @brief 设置参数
     * @param parameters 参数
     * @return 是否设置成功
     */
    bool setParameters(QVariantMap parameters);

    /**
     * @brief 获取参数
     * @return 参数
     */
    QVariantMap getParameters();

    /**
     * @brief 设置触发模式
     * @param triggerMode 触发模式（0：外触发模式，1：单次内触发模式，2：聚焦内触发模式，3：停止模式）
     * @return 设置成功返回true，失败返回false
     */
    bool setTriggerMode(int triggerMode);

    /**
     * @brief 获取触发模式
     * @return 返回触发模式 （0：外触发模式，1：单次内触发模式，2：聚焦内触发模式，3：停止模式）
     */
    int getTriggerMode();

    /**
     * @brief 精延迟通道使能
     * @param channel 通道号（0：T0 1：T1 3：T2）
     * @param enable true为使能，false为禁用
     * @return 设置成功返回true，失败返回false
     */
    bool setPreciseDelayChannelEnable(int channel, bool enable);
    
    /**
     * @brief 获取精延迟通道使能状态
     * @param channel 通道号（0：T1 1：T2 3：T3）
     * @return true为使能，false为禁用
     */
    bool getPreciseDelayChannelEnable(int channel);

    /**
     * @brief 设置精FOCUS模式下，精延迟的信号的宽度 
     * @param  widthNs_f 脉宽（单位：纳秒）
     * @return 设置成功返回true，失败返回false
     */
    bool setPreciseDelayWidth(quint32 widthNs_f);

     /**
      * @brief 获取精FOCUS模式下，精延迟的信号的宽度 
      * @return 脉宽（单位：纳秒）
      */
    quint32 getPreciseDelayWidth(); 

    /**
     * @brief 设置精FOCUS模式下，精延迟的信号的周期 
     * @param periodNs_f 周期（单位：纳秒）
     * @return 设置成功返回true，失败返回false
     */
    bool setPreciseDelayPeriod(quint32 periodNs_f);

     /**
      * @brief 获取FOCUS模式下，精延迟的信号的周期 
      * @return 周期（单位：纳秒）
      */
    quint32 getPreciseDelayPeriod();

    /**
     * @brief 设置精延迟的延时
     * @param channel 通道号（0：T0 1：T1 3：T2）
     * @param delayNs 延时（单位：纳秒）
     * @return 设置成功返回true，失败返回false
     */
    bool setPreciseDelayTime(int channel, double delayNs);

     /**
      * @brief 获取精延迟的延时
      * @param channel 通道号（0：T0 1：T1 3：T2）
      * @return 延时（单位：纳秒）
      */
    double getPreciseDelayTime(int channel);

    /**
     * @brief 设置精延迟的脉宽
     * @param channel 通道号（0：T0 1：T1 3：T2）
     * @param widthNs 脉宽（单位：纳秒）
     * @return 设置成功返回true，失败返回false
     */
    bool setPreciseDelayWidth(int channel, double widthNs);

     /**
      * @brief 获取精延迟的脉宽
      * @param channel 通道号（0：T0 1：T1 3：T2）
      * @return 脉宽（单位：纳秒）
      */
    double getPreciseDelayWidth(int channel);

    /**
     * @brief 设置IO
     * @param channel 通道号（0：通道1 1：通道2）
     * @param ioValue IO值
     * @return 设置成功返回true，失败返回false  
     */
    bool setIO(int channel, quint8 ioValue);

     /**
      * @brief 获取IO
      * @param channel 通道号（0：通道1 1：通道2）
      * @return IO值
      */
    quint8 getIO(int channel);

    /**
     * @brief 设置DA
     * @param channel 通道号（0：通道1 1：通道2）
     * @param adValue AD值
     * @return 设置成功返回true，失败返回false  
     */
    bool setDA(int channel, double daValue);

     /**
      * @brief 获取DA
      * @param channel 通道号（0：通道1 1：通道2）
      * @return DA值
      */
    double getDA(int channel);

    /**
     * @brief 获取AD值
     * @param channel 通道号（0：通道1 1：通道2）
     * @return  AD值
     */
    double getAD(int channel);

    /**
     * @brief 设置延时到闪存
     * @param channel 通道号（0:T0上升沿 1:T1上升沿 2:T1下降沿 3:T2上升沿 4:T2下降沿）
     * @param delay 延时（单位：纳秒）
     * @param saveToFlash true为保存，false为不保存
     * @return 设置成功返回true，失败返回false
     */
    bool setDelayToFlash(int , double delay, bool saveToFlash);

    /**
     * @brief 获取设置到闪存的延时
     * @param channel 通道号（0:T0上升沿 1:T1上升沿 2:T1下降沿 3:T2上升沿 4:T2下降沿）
     * @return 延时（单位：纳秒）
     */
    double getDelayToFlash(int channel);

    /**
     * @brief 设置宽度到闪存
     * @param channel 通道号（0:T0上升沿 1:T1上升沿 2:T1下降沿 3:T2上升沿 4:T2下降沿）
     * @param width 宽度（单位：纳秒）
     * @param saveToFlash true为保存，false为不保存
     * @return 设置成功返回true，失败返回false
     */
    bool setWidthToFlash(int channel, quint64 width, bool saveToFlash);

    /**
     * @brief 获取设置到闪存的宽度
     * @param channel 通道号（0:T0上升沿 1:T1上升沿 2:T1下降沿 3:T2上升沿 4:T2下降沿）
     * @return 宽度（单位：纳秒）
     */
    quint64 getWidthToFlash(int channel);
    
    /**
     * @brief 设置设备普通参数
     * @param paramsMap 参数映射表
     * @return 设置成功返回true，失败返回false
     */
    bool setArgs(const QVariantMap& m_ParamsMap);
    
    /**
     * @brief 设置设备闪存参数
     * @param paramsMap 参数映射表
     * @return 设置成功返回true，失败返回false
     */
    bool setFlashArgs(const QVariantMap& m_ParamsMap);

    /**
     * @brief ip是否有效
     * @param ipInfo  ip信息字符串
     * @param ip 返回从信息中获取的设备ip
     * @param port 返回从信息中获取的设备端口
     * @return 是否有效
     */
    static bool ipIsValid(const QString& ipInfo,QString* pINstring=nullptr,quint16* pPort=nullptr);

signals:

    /**
     * @brief 更新AD值
     */
    void updateADValue();

    /**
     * @brief 更新参数
     * @param pSender 发送者
     */
    void updateArgs(QObject* pSender);
private:

    /**
     * @brief 初始化设备参数
     */
    void initParameters();

    /**
     * @brief 更新设备参数到结构体
     */
    void updateParametersToStruct();

    /**
     * @brief 处理设备连接状态更新
     */
    static void onDeviceConnectStateUpdate(void);

    /**
     * @brief 处理设备状态更新
     * @param inst 设备状态更新结构体指针
     */
    static void onDeviceStatusUpdate(str_UpInfo_DevSts* inst);
    
    /**
     * @brief 处理校正状态更新
     * @param inst 校正状态更新结构体指针
     */
    static void onCorrectionStatusUpdate(str_UpInfo_CorrSts* inst);
    
    /**
     * @brief 处理闪存状态更新
     * @param inst 闪存状态更新结构体指针
     */
    static void onFlashStatusUpdate(str_UpInfo_FlashSts* inst);
    
    /**
     * @brief 处理AD/IO状态更新
     * @param inst AD/IO状态更新结构体指针
     */
    static void onADIOStatusUpdate(str_UpInfo_AD_IO* inst);
    
    /**
     * @brief 处理设置IP状态更新
     * @param inst 设置IP状态更新结构体指针
     */
    static void onSetIpStatusUpdate(unsigned char setIpSts);
    
    /**
     * @brief 处理命令相同状态更新
     * @param inst 命令相同状态更新结构体指针
     */ 
    static void onCmdSameStatusUpdate(void);
private:
    // 设备基本信息
    int m_deviceId;             // 设备ID
    QString m_deviceIp;         // 设备完整IP地址(包含端口)
    QString m_ipAddress;        // 拆分后的IP地址
    quint16 m_port;                 // 端口号
    QString m_subnetMask;       // 子网掩码
    QString m_gateway;          // 网关地址
    bool m_isConnected;         // 设备连接状态
    bool m_DeviceStatus;        // 设备更新状态
    bool m_CorrectionStatus;    // 校准更新状态
    bool m_FlashStatus;         // 闪存更新状态
    bool m_ADIOStatus;          // AD/IS状态更新状态
    bool m_IpStatus;            // IP更新状态
    bool m_CmdSameStatus;       // 命令同步更新状态
    mutable QMutex m_mutex;     // 用于线程安全的互斥锁
    QVariantMap m_ParamsMap;      // 参数Map
    str_Args m_Args;            // 命令参数结构体
    str_Flash m_FlashArgs;      // 闪存参数结构体
    static QMap<int,DelayDevice*> m_sDealyDeviceMap; //记录所有的DelayDevice对象
};

#endif // DELAYDEVICE_H
